home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
msjv6-5.zip
/
WINDOS.ZIP
/
BASED.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-01
|
4KB
|
136 lines
/*
BASED.C -- based pointer routines for Windows
from Microsoft Systems Journal, September 1991
Andrew Schulman (andrew@pharlap.com)
*/
#include <windows.h>
#include <malloc.h>
#include <dos.h>
#include "winio.h"
#ifdef __BORLANDC__
#include "based.h"
#endif
/* If segm==0 then use current data segment */
#define SET_DS(segm) \
if (segm) \
_asm { \
_asm push ds \
_asm mov ax, segm \
_asm mov ds, ax \
}
#define RESTORE_DS(segm) \
if (segm) _asm { \
_asm pop ds \
}
static unsigned alloc_flags = GMEM_MOVEABLE | GMEM_NODISCARD | GMEM_ZEROINIT;
/* Allocate a based heap, and return a segment value to be used
by subsequent based-heap functions */
_segment _bheapseg(size_t size)
{
WORD blk;
WORD locked;
void far *fp;
blk = GlobalAlloc(alloc_flags, size);
if (blk == 0)
return -1;
if ((fp = GlobalLock(blk)) == NULL)
{
GlobalFree(blk);
return -1;
}
locked = FP_SEG(fp);
if (LocalInit(locked, 0, size-1) == 0) /* calls GlobalLock again */
{
GlobalUnlock(blk);
GlobalFree(blk);
return -1;
}
/* succeeded -- return selector (not handle) */
return locked;
}
/* Free a based heap */
int _bfreeseg(_segment seg)
{
HANDLE h = GlobalHandle(seg); /* turn selector back into handle */
GlobalUnlock(h);
GlobalUnlock(h); // LocalInit does lock; undo it
return (GlobalFree(h) == NULL) ? 0 : -1;
}
/* Allocate a block of memory from a heap; the segment value must have
been previously returned by _bheapseg */
void _based(void) *_bmalloc(_segment segm, size_t size)
{
unsigned ret;
SET_DS(segm);
if (ret = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, size))
ret = (unsigned) LocalLock(ret);
RESTORE_DS(segm);
winio_yield();
return (void _based(void) *) ret;
}
/* Allocate storage for an array, zero-initialize the elements of the
array, and return a based pointer to the array */
void _based(void) *_bcalloc(_segment segm, size_t num, size_t size)
{
return _bmalloc(segm, num * size);
}
/* Free an allocated block */
void _bfree(_segment segm, void _based(void) *memblock)
{
if (((unsigned) memblock) == 0xFFFF)
return;
SET_DS(segm);
LocalUnlock((WORD) memblock);
LocalFree((WORD) memblock);
RESTORE_DS(segm);
winio_yield();
}
/* Helper function used by _bexpand and _brealloc */
static void _based(void) *_bresize(_segment segm,
void _based(void) *memblock, size_t size, WORD wFlags)
{
unsigned ret;
SET_DS(segm);
ret = (unsigned) LocalReAlloc((char near *) memblock, size,
wFlags | LMEM_ZEROINIT);
RESTORE_DS(segm);
winio_yield();
return (void _based(void) *) ret;
}
/* Expand or shrink an allocated block in place */
void _based(void) *_bexpand(_segment segm,
void _based(void) *memblock, size_t size)
{
return _bresize(segm, memblock, size, LMEM_FIXED);
}
/* Expand or shrink an allocated block, possibly moving it */
void _based(void) *_brealloc(_segment segm,
void _based(void) *memblock, size_t size)
{
return _bresize(segm, memblock, size, LMEM_MOVEABLE);
}
/* Return the size of a previously allocated block */
size_t _bmsize(_segment segm, void _based(void) *memblock)
{
WORD ret;
SET_DS(segm);
ret = LocalSize((WORD) memblock);
RESTORE_DS(segm);
return ret;
}